import sqlite3, json, random, time
import re, json, textwrap
from openai import OpenAI

# ---------- 配置 ----------
client = OpenAI(
    api_key="sk-RZtXMe7fMnE7J392cqTIGZ3ecV6dNwgK0mzccsk0wClWRv7d",          # 你的 Moonshot APIKey
    base_url="https://api.moonshot.cn/v1"
)
MODEL = "moonshot-v1-128k"

# 场景 & 权重（题目数量）
SCENE_TASK = {
    "首次会面": 5,
    "企业介绍": 2,
    "接待": 4,
    "谈项目": 2,
    "谈融资": 4,
    "拉合伙人": 2,
    "谈采购": 1
}

# 二级「察言观色」子话题
SUB_TOPICS = {
    "首次会面": ["场地氛围", "寒暄破冰", "微表情捕捉", "抗拒信号"],
    "企业介绍": ["数据展示时机", "团队故事", "价值主张"],
    "接待": ["行程节奏", "参观引导", "餐桌微动作"],
    "谈项目": ["需求暗线", "让步表情", "收尾信号"],
    "谈融资": ["估值攻防", "风险质疑", "条款表情"],
    "拉合伙人": ["愿景共鸣", "权责试探", "信任信号"],
    "谈采购": ["供应商评估", "价格谈判", "合同博弈"]
}

# 难度等级定义
DIFFICULTY_LEVELS = {
    "初级": "适合初学者，明显的肢体语言和表情",
    "中级": "适合有一定经验者，需要关注细节和上下文",
    "高级": "适合专业人士，需要综合多个线索进行判断"
}

# ---------- 记忆库 ----------
DB = "quiz_color.db"
conn = sqlite3.connect(DB)
c = conn.cursor()
c.execute("""
CREATE TABLE IF NOT EXISTS quiz(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scene TEXT,
    sub_topic TEXT,
    difficulty TEXT,
    question TEXT UNIQUE,
    options TEXT,
    answer TEXT,
    explanation TEXT,
    insight TEXT
)
""")
conn.commit()



def safe_parse(raw: str):
    # 1. 去掉 Markdown 代码块
    raw = re.sub(r'```(?:json)?|```', '', raw, flags=re.I).strip()
    # 2. 去掉首尾多余空白/换行
    raw = textwrap.dedent(raw).strip()
    # 3. 尝试解析
    try:
        return json.loads(raw)
    except json.JSONDecodeError:
        # 4. 仍失败就打印调试信息
        print("非法 JSON 原文：", raw)
        raise

def exists(q_text: str) -> bool:
    return c.execute("SELECT 1 FROM quiz WHERE question=?", (q_text,)).fetchone() is not None

def insert(scene, sub, difficulty, q, opts, ans, exp, insight):
    try:
        c.execute("INSERT INTO quiz(scene, sub_topic, difficulty, question, options, answer, explanation, insight) VALUES(?,?,?,?,?,?,?,?)",
                  (scene, sub, difficulty, q, opts, ans, exp, insight))
        conn.commit()
        return True
    except sqlite3.IntegrityError:
        return False

def generate_question(scene, sub_topic, difficulty):
    """
    生成单个题目并确保内容与话题相符
    """
    prompt = f"""
【任务】  
你是一位企业察言观色指导师，现在要为"{scene}"环节中的"{sub_topic}"主题设计一道商业情境中的察言观色的选择题。  
当前难度等级: {difficulty} - {DIFFICULTY_LEVELS[difficulty]}

要求：  
1. 用1-2句话描述一个真实细节场景，必须与"{sub_topic}"主题相关。
2. 场景里必须包含可观察的具体细节（微表情、动作、语气、停顿、座位、时间等）。
3. 问"接下来怎么做/对方可能怎么想/当前信号是什么"，并给出4个选项。
4. 答案唯一，解释1句话即可。
5. 提供一个"洞察要点"，说明这类情况下的核心观察点。

输出纯JSON格式：
{{"question":"","options":["A","B","C","D"],"answer":"","explanation":"", "insight":""}}

示例：
{{
  "question": "在会议室里，对方CEO在你介绍产品时，虽然面带微笑，但双手交叉放在胸前，身体略微后倾，眼神不时瞥向手表。",
  "options": [
    "A. 继续详细介绍产品功能",
    "B. 询问对方是否需要休息一下",
    "C. 加快语速尽快结束介绍",
    "D. 转向讨论合作的具体条款"
  ],
  "answer": "B",
  "explanation": "双手交叉胸前和身体后倾是防御和不耐烦的表现，看手表说明对方急于结束。",
  "insight": "身体语言比面部表情更能反映真实感受，当出现矛盾信号时，应优先关注身体姿态。"
}}

请根据场景"{scene}"、子话题"{sub_topic}"和难度等级"{difficulty}"生成题目，确保题目内容与主题相符。
"""
    
    max_retries = 3
    for attempt in range(max_retries):
        try:
            resp = client.chat.completions.create(
                model=MODEL,
                messages=[{"role": "user", "content": prompt}],
                temperature=0.9
            )
            js = safe_parse(resp.choices[0].message.content)
            
            # 验证题目内容是否与子话题相关
            if sub_topic in ["场地氛围", "寒暄破冰"] and "场地" in js["question"].lower() or "氛围" in js["question"].lower() or "寒暄" in js["question"].lower():
                return js
            elif sub_topic in ["微表情捕捉", "抗拒信号"] and ("表情" in js["question"].lower() or "抗拒" in js["question"].lower()):
                return js
            elif sub_topic in ["数据展示时机", "团队故事", "价值主张"] and (sub_topic in js["question"] or "介绍" in js["question"]):
                return js
            elif sub_topic in ["行程节奏", "参观引导", "餐桌微动作"] and (sub_topic in js["question"] or "接待" in js["question"]):
                return js
            elif sub_topic in ["需求暗线", "让步表情", "收尾信号"] and (sub_topic in js["question"] or "项目" in js["question"]):
                return js
            elif sub_topic in ["估值攻防", "风险质疑", "条款表情"] and (sub_topic in js["question"] or "融资" in js["question"]):
                return js
            elif sub_topic in ["愿景共鸣", "权责试探", "信任信号"] and (sub_topic in js["question"] or "合伙人" in js["question"]):
                return js
            elif sub_topic in ["供应商评估", "价格谈判", "合同博弈"] and (sub_topic in js["question"] or "采购" in js["question"]):
                return js
            else:
                print(f"第{attempt+1}次尝试生成题目不符合主题要求，重新生成...")
                time.sleep(1)
        except Exception as e:
            print(f"生成题目失败(尝试{attempt+1}): {e}")
            time.sleep(2)
    
    # 如果多次尝试后仍不符合要求，则使用最后一次生成的结果
    print("多次尝试后仍未完全符合主题要求，使用最后一次生成结果")
    return js

# ---------- 生成 ----------
print("开始生成20道察言观色题目...")
total_generated = 0
for scene, total in SCENE_TASK.items():
    sub_list = SUB_TOPICS[scene]
    done = 0
    # 按难度等级分配题目数量
    difficulty_distribution = {
        "初级": max(1, int(total * 0.4)),
        "中级": max(1, int(total * 0.4)),
        "高级": max(1, total - int(total * 0.4) - int(total * 0.4))
    }
    
    for difficulty, diff_total in difficulty_distribution.items():
        diff_done = 0
        while diff_done < diff_total:
            sub = random.choice(sub_list)
            try:
                js = generate_question(scene, sub, difficulty)
                if exists(js["question"]):
                    continue
                ok = insert(scene, sub, difficulty, js["question"],
                            json.dumps(js["options"], ensure_ascii=False),
                            js["answer"], js["explanation"], js["insight"])
                if ok:
                    diff_done += 1
                    done += 1
                    total_generated += 1
                    print(f"【{scene}-{sub}-{difficulty}】({diff_done}/{diff_total}) 场景总({done}/{total}) 总计({total_generated}/20)")
                    print("题干:", js["question"])
                    print("选项:", " | ".join(js["options"]))
                    print("答案:", js["answer"])
                    print("解释:", js["explanation"])
                    print("洞察:", js["insight"])
                    print("-" * 60)
                time.sleep(0.8)
            except Exception as e:
                print("生成失败:", e)
                time.sleep(2)

print("✅ 20道察言观色题已生成且不重复，数据库保存在", DB)
conn.close()